/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-03-23     jianhong       the first version
 */
#include "lcd_driver.h"
#include "font.h"
#include "Picture.h"

uint8_t Num[10]={0,1,2,3,4,5,6,7,8,9};

//从ILI93xx读出的数据为GBR格式，而我们写入的时候为RGB格式。
//通过该函数转换
//c:GBR格式的颜色值
//返回值：RGB格式的颜色值
uint16_t LCD_BGR2RGB(uint16_t c)
{
  uint16_t  r,g,b,rgb;
  b=(c>>0)&0x1f;
  g=(c>>5)&0x3f;
  r=(c>>11)&0x1f;
  rgb=(b<<11)+(g<<5)+(r<<0);
  return(rgb);

}




void Gui_Circle(uint16_t X,uint16_t Y,uint16_t R,uint16_t fc)
{//Bresenham算法
    unsigned short  a,b;
    int c;
    a=0;
    b=R;
    c=3-2*R;
    while (a<b)
    {
        Gui_DrawPoint(X+a,Y+b,fc);     //        7
        Gui_DrawPoint(X-a,Y+b,fc);     //        6
        Gui_DrawPoint(X+a,Y-b,fc);     //        2
        Gui_DrawPoint(X-a,Y-b,fc);     //        3
        Gui_DrawPoint(X+b,Y+a,fc);     //        8
        Gui_DrawPoint(X-b,Y+a,fc);     //        5
        Gui_DrawPoint(X+b,Y-a,fc);     //        1
        Gui_DrawPoint(X-b,Y-a,fc);     //        4

        if(c<0) c=c+4*a+6;
        else
        {
            c=c+4*(a-b)+10;
            b-=1;
        }
       a+=1;
    }
    if (a==b)
    {
        Gui_DrawPoint(X+a,Y+b,fc);
        Gui_DrawPoint(X+a,Y+b,fc);
        Gui_DrawPoint(X+a,Y-b,fc);
        Gui_DrawPoint(X-a,Y-b,fc);
        Gui_DrawPoint(X+b,Y+a,fc);
        Gui_DrawPoint(X-b,Y+a,fc);
        Gui_DrawPoint(X+b,Y-a,fc);
        Gui_DrawPoint(X-b,Y-a,fc);
    }

}
//画线函数，使用Bresenham 画线算法
void Gui_DrawLine(uint16_t x0, uint16_t y0,uint16_t x1, uint16_t y1,uint16_t Color)
{
int dx,             // difference in x's
    dy,             // difference in y's
    dx2,            // dx,dy * 2
    dy2,
    x_inc,          // amount in pixel space to move during drawing
    y_inc,          // amount in pixel space to move during drawing
    error,          // the discriminant i.e. error i.e. decision variable
    index;          // used for looping


    Lcd_SetXY(x0,y0);
    dx = x1-x0;//计算x距离
    dy = y1-y0;//计算y距离

    if (dx>=0)
    {
        x_inc = 1;
    }
    else
    {
        x_inc = -1;
        dx    = -dx;
    }

    if (dy>=0)
    {
        y_inc = 1;
    }
    else
    {
        y_inc = -1;
        dy    = -dy;
    }

    dx2 = dx << 1;
    dy2 = dy << 1;

    if (dx > dy)//x距离大于y距离，那么每个x轴上只有一个点，每个y轴上有若干个点
    {//且线的点数等于x距离，以x轴递增画点
        // initialize error term
        error = dy2 - dx;

        // draw the line
        for (index=0; index <= dx; index++)//要画的点数不会超过x距离
        {
            //画点
            Gui_DrawPoint(x0,y0,Color);

            // test if error has overflowed
            if (error >= 0) //是否需要增加y坐标值
            {
                error-=dx2;

                // move to next line
                y0+=y_inc;//增加y坐标值
            } // end if error overflowed

            // adjust the error term
            error+=dy2;

            // move to the next pixel
            x0+=x_inc;//x坐标值每次画点后都递增1
        } // end for
    } // end if |slope| <= 1
    else//y轴大于x轴，则每个y轴上只有一个点，x轴若干个点
    {//以y轴为递增画点
        // initialize error term
        error = dx2 - dy;

        // draw the line
        for (index=0; index <= dy; index++)
        {
            // set the pixel
            Gui_DrawPoint(x0,y0,Color);

            // test if error overflowed
            if (error >= 0)
            {
                error-=dy2;

                // move to next line
                x0+=x_inc;
            } // end if error overflowed

            // adjust the error term
            error+=dx2;

            // move to the next pixel
            y0+=y_inc;
        } // end for
    } // end else |slope| > 1
}



void Gui_box(uint16_t x, uint16_t y, uint16_t w, uint16_t h,uint16_t bc)
{
    Gui_DrawLine(x,y,x+w,y,0xEF7D);
    Gui_DrawLine(x+w-1,y+1,x+w-1,y+1+h,0x2965);
    Gui_DrawLine(x,y+h,x+w,y+h,0x2965);
    Gui_DrawLine(x,y,x,y+h,0xEF7D);
    Gui_DrawLine(x+1,y+1,x+1+w-2,y+1+h-2,bc);
}
void Gui_box2(uint16_t x,uint16_t y,uint16_t w,uint16_t h, uint8_t mode)
{
    if (mode==0)    {
        Gui_DrawLine(x,y,x+w,y,0xEF7D);
        Gui_DrawLine(x+w-1,y+1,x+w-1,y+1+h,0x2965);
        Gui_DrawLine(x,y+h,x+w,y+h,0x2965);
        Gui_DrawLine(x,y,x,y+h,0xEF7D);
        }
    if (mode==1)    {
        Gui_DrawLine(x,y,x+w,y,0x2965);
        Gui_DrawLine(x+w-1,y+1,x+w-1,y+1+h,0xEF7D);
        Gui_DrawLine(x,y+h,x+w,y+h,0xEF7D);
        Gui_DrawLine(x,y,x,y+h,0x2965);
    }
    if (mode==2)    {
        Gui_DrawLine(x,y,x+w,y,0xffff);
        Gui_DrawLine(x+w-1,y+1,x+w-1,y+1+h,0xffff);
        Gui_DrawLine(x,y+h,x+w,y+h,0xffff);
        Gui_DrawLine(x,y,x,y+h,0xffff);
    }
}


/**************************************************************************************
功能描述: 在屏幕显示一凸起的按钮框
输    入: uint16_t x1,y1,x2,y2 按钮框左上角和右下角坐标
输    出: 无
**************************************************************************************/
void DisplayButtonDown(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2)
{
    Gui_DrawLine(x1,  y1,  x2,y1, GRAY2);  //H
    Gui_DrawLine(x1+1,y1+1,x2,y1+1, GRAY1);  //H
    Gui_DrawLine(x1,  y1,  x1,y2, GRAY2);  //V
    Gui_DrawLine(x1+1,y1+1,x1+1,y2, GRAY1);  //V
    Gui_DrawLine(x1,  y2,  x2,y2, WHITE);  //H
    Gui_DrawLine(x2,  y1,  x2,y2, WHITE);  //V
}

/**************************************************************************************
功能描述: 在屏幕显示一凹下的按钮框
输    入: uint16_t x1,y1,x2,y2 按钮框左上角和右下角坐标
输    出: 无
**************************************************************************************/
void DisplayButtonUp(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2)
{
    Gui_DrawLine(x1,  y1,  x2,y1, WHITE); //H
    Gui_DrawLine(x1,  y1,  x1,y2, WHITE); //V

    Gui_DrawLine(x1+1,y2-1,x2,y2-1, GRAY1);  //H
    Gui_DrawLine(x1,  y2,  x2,y2, GRAY2);  //H
    Gui_DrawLine(x2-1,y1+1,x2-1,y2, GRAY1);  //V
    Gui_DrawLine(x2  ,y1  ,x2,y2, GRAY2); //V
}


void Gui_DrawFont_GBK16(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s)
{
    unsigned char i,j;
    unsigned short k,x0;
    x0=x;

    while(*s)
    {
        if((*s) < 128)
        {
            k=*s;
            if (k==13)
            {
                x=x0;
                y+=16;
            }
            else
            {
                if (k>32) k-=32; else k=0;

                for(i=0;i<16;i++)
                for(j=0;j<8;j++)
                    {
                        if(asc16[k*16+i]&(0x80>>j)) Gui_DrawPoint(x+j,y+i,fc);
                        else
                        {
                            if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
                        }
                    }
                x+=8;
            }
            s++;
        }

        else
        {


            for (k=0;k<hz16_num;k++)
            {
              if ((hz16[k].Index[0]==*(s))&&(hz16[k].Index[1]==*(s+1)))
              {
                    for(i=0;i<16;i++)
                    {
                        for(j=0;j<8;j++)
                            {
                                if(hz16[k].Msk[i*2]&(0x80>>j))  Gui_DrawPoint(x+j,y+i,fc);
                                else {
                                    if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
                                }
                            }
                        for(j=0;j<8;j++)
                            {
                                if(hz16[k].Msk[i*2+1]&(0x80>>j))    Gui_DrawPoint(x+j+8,y+i,fc);
                                else
                                {
                                    if (fc!=bc) Gui_DrawPoint(x+j+8,y+i,bc);
                                }
                            }
                    }
                }
              }
            s+=2;x+=16;
        }

    }
}

void Gui_DrawFont_GBK24(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s)
{
    unsigned char i,j;
    unsigned short k;

    while(*s)
    {
        if( *s < 0x80 )
        {
            k=*s;
            if (k>32) k-=32; else k=0;

            for(i=0;i<16;i++)
            for(j=0;j<8;j++)
                {
                    if(asc16[k*16+i]&(0x80>>j))
                    Gui_DrawPoint(x+j,y+i,fc);
                    else
                    {
                        if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
                    }
                }
            s++;x+=8;
        }
        else
        {

            for (k=0;k<hz24_num;k++)
            {
              if ((hz24[k].Index[0]==*(s))&&(hz24[k].Index[1]==*(s+1)))
              {
                    for(i=0;i<24;i++)
                    {
                        for(j=0;j<8;j++)
                            {
                                if(hz24[k].Msk[i*3]&(0x80>>j))
                                Gui_DrawPoint(x+j,y+i,fc);
                                else
                                {
                                    if (fc!=bc) Gui_DrawPoint(x+j,y+i,bc);
                                }
                            }
                        for(j=0;j<8;j++)
                            {
                                if(hz24[k].Msk[i*3+1]&(0x80>>j))    Gui_DrawPoint(x+j+8,y+i,fc);
                                else {
                                    if (fc!=bc) Gui_DrawPoint(x+j+8,y+i,bc);
                                }
                            }
                        for(j=0;j<8;j++)
                            {
                                if(hz24[k].Msk[i*3+2]&(0x80>>j))
                                Gui_DrawPoint(x+j+16,y+i,fc);
                                else
                                {
                                    if (fc!=bc) Gui_DrawPoint(x+j+16,y+i,bc);
                                }
                            }
                    }
              }
            }
            s+=2;x+=24;
        }
    }
}
void Gui_DrawFont_Num32(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint16_t num)
{
    unsigned char i,j,k,c;
    //lcd_text_any(x+94+i*42,y+34,32,32,0x7E8,0x0,sz32,knum[i]);
//  w=w/8;

    for(i=0;i<32;i++)
    {
        for(j=0;j<4;j++)
        {
            c=*(sz32+num*32*4+i*4+j);
            for (k=0;k<8;k++)
            {

                if(c&(0x80>>k)) Gui_DrawPoint(x+j*8+k,y+i,fc);
                else {
                    if (fc!=bc) Gui_DrawPoint(x+j*8+k,y+i,bc);
                }
            }
        }
    }
}

void Redraw_Mainmenu(void)
{

    Lcd_Clear(GRAY0);

    Gui_DrawFont_GBK16(16,2,BLUE,GRAY0,"全动电子技术");
    Gui_DrawFont_GBK16(16,20,RED,GRAY0,"液晶测试程序");

    DisplayButtonUp(15,38,113,58); //x1,y1,x2,y2
    Gui_DrawFont_GBK16(16,40,GREEN,GRAY0,"颜色填充测试");

    DisplayButtonUp(15,68,113,88); //x1,y1,x2,y2
    Gui_DrawFont_GBK16(16,70,BLUE,GRAY0,"文字显示测试");

    DisplayButtonUp(15,98,113,118); //x1,y1,x2,y2
    Gui_DrawFont_GBK16(16,100,RED,GRAY0,"图片显示测试");


    //Gui_DrawFont_GBK16(16,120,BLUE,GRAY0,"Welcome");
    Gui_DrawFont_GBK16(16,140,RED,GRAY0, "Welcome");

    Gui_DrawFont_Num32(100,125,RED,GRAY0,Num[5]);
    rt_thread_mdelay(1000);
    Gui_DrawFont_Num32(100,125,RED,GRAY0,Num[4]);
    rt_thread_mdelay(1000);
    Gui_DrawFont_Num32(100,125,RED,GRAY0,Num[3]);
    rt_thread_mdelay(1000);
    Gui_DrawFont_Num32(100,125,RED,GRAY0,Num[2]);
    rt_thread_mdelay(1000);
    Gui_DrawFont_Num32(100,125,RED,GRAY0,Num[1]);
    rt_thread_mdelay(1000);
    Gui_DrawFont_Num32(100,125,RED,GRAY0,Num[0]);
}

//简单刷屏测试
void Color_Test(void)
{
    uint8_t i=1;
    Lcd_Clear(GRAY0);

    Gui_DrawFont_GBK16(20,10,BLUE,GRAY0,"颜色填充测试");
    rt_thread_mdelay(1200);

    while(i--)
    {
        Lcd_Clear(WHITE); rt_thread_mdelay(500);
        Lcd_Clear(BLACK); rt_thread_mdelay(500);
        Lcd_Clear(RED);   rt_thread_mdelay(500);
        Lcd_Clear(GREEN); rt_thread_mdelay(500);
        Lcd_Clear(BLUE);  rt_thread_mdelay(500);
    }
}

//文字显示测试
//16位BMP 40X40 QQ图像取模数据
//Image2LCD取模选项设置
//水平扫描
//16位
//40X40
//不包含图像头数据
//自左至右
//自顶至底
//低位在前
void showimage(const unsigned char *p) //显示40*40 QQ图片
{
    int i,j,k;
    unsigned char picH,picL;
    Lcd_Clear(GRAY0);
    Gui_DrawFont_GBK16(16,10,BLUE,GRAY0,"图片显示测试");
    rt_thread_mdelay(1000);

    Lcd_Clear(GRAY0);
    for(k=0;k<6;k++)
    {
        for(j=0;j<8;j++)
        {
            Lcd_SetRegion(40*j,40*k,40*j+39,40*k+39);       //坐标设置
            for(i=0;i<40*40;i++)
             {
                picL=*(p+i*2);  //数据低位在前
                picH=*(p+i*2+1);
                Lcd_WriteData_16Bit(picH<<8|picL);
             }
         }
    }
}

//测试数码管字体
void Num_Test(void)
{
    uint8_t i=0;
    Lcd_Clear(GRAY0);
    Gui_DrawFont_GBK16(16,20,RED,GRAY0,"Num Test");
    rt_thread_mdelay(1000);
    Lcd_Clear(GRAY0);

    for(i=0;i<10;i++)
    {
    Gui_DrawFont_Num32((i%3)*40,32*(i/3)+30,RED,GRAY0,Num[i+1]);
    rt_thread_mdelay(100);
    }

}
//中英文显示测试
void Font_Test(void)
{
    Lcd_Clear(GRAY0);
    Gui_DrawFont_GBK16(16,10,BLUE,GRAY0,"文字显示测试");

    rt_thread_mdelay(1000);
    Lcd_Clear(GRAY0);
    Gui_DrawFont_GBK16(16,30,RED,GRAY0,"全动电子技术");
    Gui_DrawFont_GBK16(16,50,BLUE,GRAY0,"专注液晶批发");
    Gui_DrawFont_GBK16(16,70,RED,GRAY0, "全程技术支持");
    Gui_DrawFont_GBK16(0,100,BLUE,GRAY0,"Tel:15989313508");
    Gui_DrawFont_GBK16(0,130,RED,GRAY0, "www.qdtech.net");
    rt_thread_mdelay(1500);
}

//综合测试函数
void QDTFT_Test_Demo(void)
{
    Lcd_Init();
    LCD_LED_SET;//通过IO控制背光亮
    Redraw_Mainmenu();//绘制主菜单(部分内容由于分辨率超出物理值可能无法显示)
    Color_Test();//简单纯色填充测试
    Num_Test();//数码管字体测试
    Font_Test();//中英文显示测试
    showimage(gImage_qq);//图片显示示例
    rt_thread_mdelay(1500);
    LCD_LED_CLR;//IO控制背光灭
}

